﻿using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace Pathfinding
{
    public class OctreeAStar : MonoBehaviour
    {
        public OctreeBuilder octree; //八叉树构建器
        private AStarSearcher<Graph<OctreeNode, int>, OctreeNode> _astar; //A星搜索器
        private Stack<OctreeNode> _path; //存储路径的栈
        [SerializeField] private Transform start; //寻路起点

        [SerializeField] private Transform end; //寻路终点

        //当该值位false时会进行一次寻路，寻路完成后自动为true
        [SerializeField] private bool isFindPathEnd;

        private void Start()
        {
            _astar = new AStarSearcher<Graph<OctreeNode, int>, OctreeNode>(octree.Octree.NavGraph);
            _path = new Stack<OctreeNode>();
            startPos = start.position;
        }

        private float alpha = 0;
        private Vector3 startPos = Vector3.zero;
        private int pathIndex = 0;
        private void Update()
        {
            if (isFindPathEnd)
            {
                var nextPosition = _path.ToList()[pathIndex].NodeCube.center;
                if (Vector3.Distance(start.position, nextPosition) > 1)
                {
                    start.position = Vector3.Lerp(startPos, nextPosition, alpha);
                }
                else
                {
                    startPos = start.position;
                    pathIndex++;
                    alpha = 0;
                }
            }

            if (isFindPathEnd) return;
            //将起点与终点的位置转化为树中节点，然后进行寻路
            var s = octree.Octree.GetNodeByPos(octree.Octree.RootNode, start.position);
            var e = octree.Octree.GetNodeByPos(octree.Octree.RootNode, end.position);
            if(e.Type == NodeType.Obstacles) return;
            _astar.FindPath(s, e, _path);
            isFindPathEnd = true;
        }

        private void OnDrawGizmos()
        {
            if (!Application.isPlaying) return;
            var prevPos = start.position;
            foreach (var n in _path)
            {
                Gizmos.color = Color.red;
                Gizmos.DrawLine(prevPos, n.NodeCube.center);
                prevPos = n.NodeCube.center;
            }

            Gizmos.DrawLine(prevPos, end.position);
        }
    }
}